import { ref, Ref } from 'vue';

interface RequestOptions<T> {
  manual?: boolean;
  initialData?: T;
  onSuccess?: (data: T) => void;
  onError?: (e: Error) => void;
}

interface RequestResult<T> {
  data: Ref<T | undefined>;
  loading: Ref<boolean>;
  error: Ref<Error | undefined>;
  run: (...args: any[]) => Promise<T>;
}

/**
 * 封装异步请求的组合式函数
 * @param service 异步请求函数
 * @param options 配置选项
 */
export function useRequest<T>(
  service: (...args: any[]) => Promise<T>,
  options: RequestOptions<T> = {}
): RequestResult<T> {
  const { manual = false, initialData, onSuccess, onError } = options;

  const data = ref<T | undefined>(initialData) as Ref<T | undefined>;
  const loading = ref<boolean>(false);
  const error = ref<Error>();

  const run = async (...args: any[]): Promise<T> => {
    loading.value = true;
    error.value = undefined;

    try {
      const result = await service(...args);
      data.value = result;
      onSuccess?.(result);
      return result;
    } catch (e) {
      error.value = e as Error;
      onError?.(e as Error);
      throw e;
    } finally {
      loading.value = false;
    }
  };

  if (!manual) {
    run();
  }

  return { data, loading, error, run };
}
